<?php

/**
 *Simple CRUD Code Generator
 *Email:  support@crazedcoders.com
 *Website: http://www.crazedcoders.com/
 *Copyright (C) 2007 CrazedCoders
 *
 *This program is free software: you can redistribute it and/or modify
 *it under the terms of the GNU General Public License as published by
 *the Free Software Foundation, either version 3 of the License, or
 *(at your option) any later version.
 *
 *THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *SOFTWARE.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*************************************************
 * include files
 *************************************************/
require_once( 'commonfunctions.php' );
require_once( 'con2.php' );
require_once( 'function.copyr.php' );
require_once( 'generateAppController.php' );
require_once( 'generateAppModel.php' );
require_once( 'generateCommandForTable.php' );
require_once( 'generateDaoForTable.php' );
require_once( 'generateDelegates.php' );
require_once( 'generateEclipseFiles.php' );
require_once( 'generateActionScriptPropertiesFile.php' );
require_once( 'generateEventForTable.php' );
require_once( 'generateModelForTable.php' );
require_once( 'generateRemotingConfig.php' );
require_once( 'generateServicesMxml.php' );
require_once( 'generateTestForTable.php' );
require_once( 'generateTestMxml.php' );
require_once( 'generateVOs.php' );

echo
"<html>
<head>
	<title>Simple CRUD code generator - CrazedCoders(c)</title>
</head>
<style>
body, td, input { font-family:tahoma;font-size:12px;}
input {width:200px}
h1 {font-size:14px; color:#000099; font-weight:bold}
</style>
<body>
";

# easier viewing
echo "<code><pre>";

/*************************************************
 * configuration starts here
 * run this on a webserver using the appropriate
 * get calls
 *
 * ie:
 * http://dev.crazedcoders.com:8100/flashservices/services/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.loginscreen&dbhost=localhost&dbuser=sa&dbpass=passwd99&dbname=rubba
 *************************************************/

if ( ! array_key_exists( 'dbtype', $_GET )  || strlen($_GET['dbtype']) < 2) {
	con::$dbtype = 'mysql';
	echo "<font color=\"#dd2222\">\nNo database type specified in querystring for (dbtype).\n".
		"Using default dbtype: ".con::$dbtype."</font>\n";
}
else {
	con::$dbtype = $_GET['dbtype'];
}

if ( ! array_key_exists( 'dbname', $_GET )  || strlen($_GET['dbname']) < 2) {
	die("<font color=\"#dd2222\">Fatal Error:</font> No database name specified specified in querystring (dbname)\n
Proper Syntax is:
generateDaos.php?package=[packagename]&dbhost=[dbserverAddress]&dbuser=[dbUsername]&dbpass=[password]&dbname=[dbname]\n
Example:
http://shared.crazedcoders.com/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.sample&dbhost=db.crazedCoders.com&dbuser=root&dbpass=password&dbname=sample
");
}
else {
	con::$dbname = $_GET['dbname'];
}

if ( ! array_key_exists( 'dbhost', $_GET ) || strlen($_GET['dbhost']) < 2) {
	die("<font color=\"#dd2222\">Fatal Error:</font> No database host specified specified in querystring (dbhost)\n
Proper Syntax is:
generateDaos.php?package=[packagename]&dbhost=[dbserverAddress]&dbuser=[dbUsername]&dbpass=[password]&dbname=[dbname]\n
Example:
http://shared.crazedcoders.com/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.sample&dbhost=db.crazedCoders.com&dbuser=root&dbpass=password&dbname=sample
");
}
else {
	con::$dbhost= $_GET['dbhost'];
}

if ( ! array_key_exists( 'dbpass', $_GET ) ) {
	die("<font color=\"#dd2222\">Fatal Error:</font> No database password specified specified in querystring (dbpass)\n
Proper Syntax is:
generateDaos.php?package=[packagename]&dbhost=[dbserverAddress]&dbuser=[dbUsername]&dbpass=[password]&dbname=[dbname]\n
Example:
http://shared.crazedcoders.com/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.sample&dbhost=db.crazedCoders.com&dbuser=root&dbpass=password&dbname=sample
");
}
else {
	con::$dbpass= $_GET['dbpass'];
}

if ( ! array_key_exists( 'dbuser', $_GET )  || strlen($_GET['dbuser']) < 2) {
	die("<font color=\"#dd2222\">Fatal Error:</font> No database user specified specified in querystring (dbuser)\n
Proper Syntax is:
generateDaos.php?package=[packagename]&dbhost=[dbserverAddress]&dbuser=[dbUsername]&dbpass=[password]&dbname=[dbname]\n
Example:
http://shared.crazedcoders.com/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.sample&dbhost=db.crazedCoders.com&dbuser=root&dbpass=password&dbname=sample
");
}
else {
	con::$dbuser= $_GET['dbuser'];
}

if ( ! array_key_exists( 'package', $_GET )  || strlen($_GET['package']) < 2) {
	die("<font color=\"#dd2222\">Fatal Error:</font> No package specified specified in querystring (package)\n
Proper Syntax is:
generateDaos.php?package=[packagename]&dbhost=[dbserverAddress]&dbuser=[dbUsername]&dbpass=[password]&dbname=[dbname]\n
Example:
http://shared.crazedcoders.com/phpDaoGenerator/generateDaos.php?package=com.crazedcoders.sample&dbhost=db.crazedCoders.com&dbuser=root&dbpass=password&dbname=sample
");
}
else {
	$package = strtolower($_GET['package']);
}

echo "<b>Using the following settings:</b>\n\n";
echo "database name     (dbname=) : <font "
						."color=\"#33cc33\">".con::$dbname."</font>\n";
echo "database password (dbpass=) : <font "
						."color=\"#33cc33\">".con::$dbpass."</font>\n";
echo "database username (dbuser=) : <font "
						."color=\"#33cc33\">".con::$dbuser."</font>\n";
echo "database hostname (dbhost=) : <font "
						."color=\"#33cc33\">".con::$dbhost."</font>\n\n";

$tstamp = $_SERVER['REQUEST_TIME'];
//$tablenames = split( ':', $_GET['tables'] );
	// will be scanned from database

# log hits
$fp = fopen("../log.html", "a");
fputs($fp,date("m.d,  h:i:s").', '.GetHostByName($_SERVER['REMOTE_ADDR']).', Initiated, Server: '.con::$dbhost.'<br/>');
fclose( $fp);

#$dbConn = mysql_connect( 'localhost', 'phpuser', 'password' );
#mysql_select_db( 'test' );
if( con::$dbtype == 'mysql' ) {
}
else if ( con::$dbtype == 'mssql' ) {
}

$relativeRoot = $_SERVER['DOCUMENT_ROOT'].'/php/generated';// '/'.$tstamp;

if( con::$dbtype == 'mysql' ) {
	$dbConn = @mysql_connect( con::$dbhost, con::$dbuser,
			con::$dbpass ) or die('<font color="red">Could not connect: ' . mysql_error().'</font>');
	mysql_select_db( $_GET['dbname'] );
}
else if ( con::$dbtype == 'mssql' ) {
	$dbConn = @mssql_connect( con::$dbhost, con::$dbuser,
			con::$dbpass ) or die('<font color="red">Unable to connect to server</font>');
	mssql_select_db( $_GET['dbname'] );
}

# zip stuff
if(GetHostByName($_SERVER['REMOTE_ADDR']) == '127.0.0.1'){
	$zipName = 'testing.zip';}
else{
	$zipName = $tstamp.'_'.str_replace('.','_',GetHostByName($_SERVER['REMOTE_ADDR'])).'.zip';}
#echo 'zipping...'/php/generated/'.$zipName.'<br />';
$zip = new ZipArchive();
$filename = $_SERVER['DOCUMENT_ROOT'].'/php/generated/'.$zipName;
if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
   echo("cannot open <$filename>\n");
}


/*************************************************
 * configuration ends here
 *************************************************/

/*************************************************
 * internal constants
 *************************************************/
con::$package = $package;
# convert package to relative path
con::$packagePath = str_replace( '.', '/', $package );
#echo "packagePath: $packagePath;";
#echo "package: $package;";
con::$relativePath = $relativeRoot."/amfphp/services/".con::$packagePath;
con::$absolutePath = "amfphp/services/".con::$packagePath;

/*foreach( split( "\.", $package ) as $tmp1=>$tmp2) {
		$relativeVoPath .= "../";
}*/
con::$relativeVoPath .= $relativeRoot."/amfphp/services/vo/".con::$packagePath;
con::$absoluteVoPath .= "amfphp/services/vo/".con::$packagePath;

con::$relativeFlexRootPath = $relativeRoot."/".$_GET['dbname']."_flex/";
con::$absoluteFlexRootPath = $_GET['dbname']."_flex/";

con::$relativeFlexSrcPath= $relativeRoot."/".$_GET['dbname']."_flex/src";
con::$absoluteFlexSrcPath= $_GET['dbname']."_flex/src";

con::$relativeFlexPath = con::$relativeFlexSrcPath."/".con::$packagePath;
con::$absoluteFlexPath = con::$absoluteFlexSrcPath."/".con::$packagePath;

con::$relativeFlexVoPath = con::$relativeFlexPath."/vo";
con::$absoluteFlexVoPath = $_GET['dbname']."_flex/src/".con::$packagePath."/vo";

#make sure dirs exist
if( ! file_exists( con::$relativePath ) ) {
	mkdir( con::$relativePath, 0, true );
}
if( ! file_exists( con::$relativeVoPath ) ) {
	mkdir( con::$relativeVoPath, 0, true );
}
if( ! file_exists( con::$relativeFlexVoPath ) ) {
	mkdir( con::$relativeFlexVoPath, 0, true );
}


// copy the skeleton directory structure first
copyr( './flexSkel/', con::$relativeFlexRootPath, true, false);
$zip->addFile(con::$relativeFlexRootPath.'/lib/cairngorm.swc',
	con::$absoluteFlexRootPath.'lib/cairngorm.swc');
$zip->addFile(con::$relativeFlexRootPath.'/src/services-config.xml',
	con::$absoluteFlexRootPath.'src/services-config.xml');

//$zip->addFile(con::$relativeFlexSrcPath.'/com/crazedcoders/lib/control/ViewController.as',
//		con::$absoluteFlexSrcPath.'/com/crazedcoders/lib/control/ViewController.as');
//$zip->addFile(con::$relativeFlexSrcPath.'/com/crazedcoders/lib/event/CommandEvent.as',
//		con::$absoluteFlexSrcPath.'/com/crazedcoders/lib/event/CommandEvent.as');
$zip->addFile(con::$relativeFlexSrcPath.'/com/crazedcoders/lib/interfaces/IView.as',
		con::$absoluteFlexSrcPath.'/com/crazedcoders/lib/interfaces/IView.as');
$zip->addFile(con::$relativeFlexSrcPath.'/com/crazedcoders/lib/structure/TypedArrayCollection.as',
		con::$absoluteFlexSrcPath.'/com/crazedcoders/lib/structure/TypedArrayCollection.as');


//if( ! is_file( con::$relativeFlexRootPath.'/.actionScriptProperties' ) ) {
//	copyr( './flexSkel/.actionScriptProperties',
//		con::$relativeFlexRootPath.'/.actionScriptProperties', true, true);
//}
if( ! is_file( con::$relativeFlexRootPath.'/.flexProperties' ) ) {
	copyr( './flexSkel/.flexProperties',
			con::$relativeFlexRootPath.'/.flexProperties', true, true);
}
	$zip->addFile(con::$relativeFlexRootPath.'/.flexProperties',
		con::$absoluteFlexRootPath.'.flexProperties');

# copy a version of StdFunc if not exists
$defaultStdFuncPath = "StdFunc.php";
$stdFuncPath = con::$relativePath."/StdFunc.php";
if( ! file_exists( $stdFuncPath ) ) {
	//echo "<font color=\"#ff0000\">Installed new StdFunc.php in $stdFuncPath</font><br />";
	copy($defaultStdFuncPath, $stdFuncPath );
	# need to edit this file
	$fp = fopen($stdFuncPath , "r");
	$data = fread($fp, filesize($stdFuncPath ));
	fclose ($fp);
	# now change the query strings
	$data = str_replace('DBNAME_PLACEHOLDER', con::$dbname,$data);
	$data = str_replace('DBHOST_PLACEHOLDER', con::$dbhost, $data);
	$data = str_replace('DBUSER_PLACEHOLDER', con::$dbuser, $data);
	$data = str_replace('DBPASS_PLACEHOLDER', con::$dbpass, $data);
	$fp = fopen($stdFuncPath, "w");
	fputs($fp,$data);
	fclose( $fp);

}
else {
	//echo "<font color=\"#33aa33\">Using already installed StdFunc.php in $stdFuncPath</font><br />";
}


# get tablenames
$query = "SELECT table_name FROM information_schema.tables
			WHERE
				table_name NOT LIKE 'sys%'
				AND table_name <> 'dtproperties'";
if( con::$dbtype == 'mysql' ) {
	$query.= "
				AND table_schema <> 'INFORMATION_SCHEMA'
				AND table_schema = '".con::$dbname."'; ";
}
else if ( con::$dbtype == 'mssql' ) {
	$query.= "
				AND table_schema <> 'INFORMATION_SCHEMA'
				AND table_catalog = '".con::$dbname."'; ";
}

//echo " query: $query\n";
$tablenames = array();
if( con::$dbtype == 'mysql' ) {
	$rid = mysql_query( $query, $dbConn );
	while( $assoc = mysql_fetch_assoc( $rid ) ) {
		array_push( $tablenames, $assoc['table_name'] );
	}
}
else if( con::$dbtype == 'mssql' ) {
	$rid = mssql_query( $query, $dbConn );
	while( $assoc = mssql_fetch_assoc( $rid ) ) {
		array_push( $tablenames, $assoc['table_name'] );
	}
}


# get columns descriptions
//echo "con::\$dbtype : ".con::$dbtype."\n";
if( con::$dbtype == 'mysql' ) {
	$query = "SELECT * FROM Information_Schema.Columns WHERE table_schema = '"
		.con::$dbname."' ";
}
else if ( con::$dbtype == 'mssql' ) {
	$query = "SELECT * FROM Information_Schema.Columns WHERE table_catalog = '"
		.con::$dbname."' ";
}
$endquery = "";
for( $i = 0; $i < sizeof($tablenames); $i++ ) {
		$name = $tablenames[$i];
		if( $i != 0 ) {
				$query .= " OR ";
		}
		else{
			$query .= " AND ( ";
			$endquery .= " ) ";
		}
		$query .= " table_name = '". $name . "'";
}
$query .= $endquery;
//echo " query: $query\n";
# do the mssql call
if( con::$dbtype == 'mysql' ) {
	$rid = mysql_query( $query );
}
else if ( con::$dbtype == 'mssql' ) {
	$rid = mssql_query( $query );
}
con::$tables = Array(); # store the tables in an assoc
while( $assoc =
		(con::$dbtype=='mysql')?mysql_fetch_assoc( $rid )
		:( (
			con::$dbtype=='mssql')?mssql_fetch_assoc( $rid )
			:array()
			) ) {
		if( ! array_key_exists( $assoc['TABLE_NAME'], con::$tables ) ) {
				con::$tables[$assoc['TABLE_NAME']] = array();
		}
		array_push( con::$tables[$assoc['TABLE_NAME']] ,
						array( $assoc['COLUMN_NAME'],$assoc['DATA_TYPE']));
}

# fixme: improve CRUD generation to detect mapping tables

$query =
## only selects primary keys
#"SELECT
#		C.table_name,
#		C.column_name,
#		C.data_type,
#		T.constraint_type
#	FROM
#		Information_Schema.Table_Constraints T
#		INNER JOIN Information_Schema.Key_Column_Usage K
#		ON T.constraint_name = K.constraint_name
#		INNER JOIN Information_Schema.Columns C
#		ON
#			C.table_name = T.table_name
#			AND C.table_catalog = T.table_catalog
#			AND C.column_name = K.column_name
#	WHERE
#		K.table_catalog = '".$_GET['dbname']."'
#		AND T.constraint_type='PRIMARY KEY'
#";

# selects both primary and foreign keys
((con::$dbtype == 'mysql')?
"SELECT
	C.table_name
	,A.column_name
	,O.data_type
	,C.constraint_type
	,A.referenced_table_name
	,A.referenced_column_name
	-- ,O.*
	FROM information_schema.table_constraints C
	LEFT JOIN information_schema.key_column_usage A
		ON C.constraint_name = A.constraint_name
		AND C.table_name = A.table_name
	LEFT JOIN information_schema.columns O
		ON C.table_schema= O.table_schema
		AND A.table_name = O.table_name
		AND A.column_name = O.column_name
	WHERE ( C.constraint_type = 'FOREIGN KEY'
		OR C.constraint_type = 'PRIMARY KEY' )
		AND C.table_name <> 'dtproperties'
		AND C.table_schema = '".con::$dbname."'
;
":"").
((con::$dbtype == 'mssql')?
"SELECT
	C.table_name
	,O.column_name
	,O.data_type
	,C.constraint_type
	,D.table_name AS 'referenced_table_name'
	,B.column_name AS 'referenced_column_name'
	-- ,O.*
	FROM information_schema.table_constraints C
	LEFT JOIN information_schema.key_column_usage A
		ON C.constraint_name = A.constraint_name
	LEFT JOIN information_schema.columns O
		ON C.table_catalog = O.table_catalog
		AND A.table_name = O.table_name
		AND A.column_name = O.column_name
	LEFT JOIN information_schema.referential_constraints R
		ON C.constraint_name = R.constraint_name
	LEFT JOIN information_schema.table_constraints D
		ON R.unique_constraint_name = D.constraint_name
	LEFT JOIN information_schema.constraint_column_usage B
		ON D.constraint_name = B.constraint_name
	WHERE ( C.constraint_type = 'FOREIGN KEY'
		OR C.constraint_type = 'PRIMARY KEY' )
		AND C.table_name <> 'dtproperties';
":"")

;

//echo "query: $query\n";

if( con::$dbtype == 'mysql' ) {
	$rid = mysql_query( $query, $dbConn );
}
else if ( con::$dbtype == 'mssql' ) {
	$rid = mssql_query( $query, $dbConn );
}


$lowertablenames = array();

for( $i = 0; $i< sizeof( $tablenames ); $i++ ) {
	$lowertablenames[$i] = strtolower( $tablenames[$i] ) ;
}

$foreignKeyRows = array();	# keep a reference of all the foreign key rows
							# fetched

#echo "var_dump( \con::$tables );";
#var_dump( con::$tables );


// delete the AppController_include.as file because we will be appending to it
if( file_exists( con::$relativeFlexPath."/control/"
						."AppController_include.as" ) ) {
	unlink( con::$relativeFlexPath."/control/"
						."AppController_include.as" );
}

// loop through the tables
while( $assoc = ((con::$dbtype=='mysql')?mysql_fetch_assoc( $rid )
	:( (con::$dbtype=='mssql')?mssql_fetch_assoc($rid)
		:array() )) ) {
	// add more info to con::$tables
	//$colIndex = array_search( $assoc['column_name'],
	//	   con::$tables[$assoc['table_name']] );
	$colIndex = 0;
	//echo "assoc from megasql call: ";
	//var_dump( $assoc );
	//echo "\n";
	while( con::$tables[$assoc['table_name']][$colIndex][0] !=
			$assoc['column_name'] ) {
		$colIndex++;
		if( $colIndex >= sizeof( con::$tables[$assoc['table_name']] ) ) {
			break;
		}
	}
	if( $colIndex < sizeof( con::$tables[$assoc['table_name']] ) ) {
		con::$tables[$assoc['table_name']][$colIndex][2] = $assoc;
	}


	// deal with tables with pkeys
	$index = array_search(
					strtolower( $assoc['table_name'] ),
					$lowertablenames
				);
	if( !( $index === FALSE ) ) {
		/*
		if( $assoc['constraint_type'] == 'PRIMARY KEY' )  {
			// write Dao
			$exportDao = generateDaoForTable( $assoc, con::$relativePath );
			$fh = fopen( con::$relativePath."/".toCamelCase(
						$assoc['table_name'])."Dao.php", "w" );
			fwrite( $fh, $exportDao );
			//echo con::$relativePath."/".toCamelCase(
					$assoc['table_name'])."Dao.php <br />" ;
			fclose( $fh );

			// write Command
			$exportCommand = generateCommandForTable( $assoc );
			if( ! file_exists( con::$relativeFlexPath."/command/" ) ) {
				mkdir (con::$relativeFlexPath."/command/" ) ;
			}
			$fh = fopen( con::$relativeFlexPath."/command/".toCamelCase(
						$assoc['table_name'])."Command.as", "w" );
			fwrite( $fh, $exportCommand );
			//echo ( con::$relativeFlexPath."/command/".toCamelCase(
						$assoc['table_name'])."Command.as<br />" );
			fclose( $fh );

			// write Event
			$exportEvent = generateEventForTable( $assoc );
			if( ! file_exists( con::$relativeFlexPath."/event/" ) ) {
				mkdir (con::$relativeFlexPath."/event/" ) ;
			}
			$fh = fopen( con::$relativeFlexPath."/event/".toCamelCase(
						$assoc['table_name'])."Event.as", "w" );
			fwrite( $fh, $exportEvent );
			//echo ( con::$relativeFlexPath."/event/".toCamelCase(
						$assoc['table_name'])."Event.as<br />" );
			fclose( $fh );
			// write Model
			$exportModel = generateModelForTable( $assoc );
			if( ! file_exists( con::$relativeFlexPath."/model/" ) ) {
				mkdir (con::$relativeFlexPath."/model/" ) ;
			}
			$fh = fopen( con::$relativeFlexPath."/model/".toCamelCase(
						$assoc['table_name'])."Model.as", "w" );
			fwrite( $fh, $exportModel );
			//echo ( con::$relativeFlexPath."/model/".toCamelCase(
						$assoc['table_name'])."Model.as<br />" );
			fclose( $fh );
			// write Test
			$export = generateTestForTable( $assoc );
			if( ! file_exists( con::$relativeFlexPath."/test/" ) ) {
				mkdir (con::$relativeFlexPath."/test/" ) ;
			}
			$fh = fopen( con::$relativeFlexPath."/test/".toCamelCase(
						$assoc['table_name'])."Test.mxml", "w" );
			fwrite( $fh, $export );
			//echo ( con::$relativeFlexPath."/model/".toCamelCase(
						$assoc['table_name'])."Test.mxml<br />" );
			fclose( $fh );
			// write AppController
			$export = generateAppControllerForTable( $assoc );
			if( ! file_exists( con::$relativeFlexPath."/control/" ) ) {
				mkdir (con::$relativeFlexPath."/control/" ) ;
			}
			$fh = fopen( con::$relativeFlexPath."/control/"
						."AppController_include.as", "a" );
					// we append here since we deleted the file at the
					// beginning
			fwrite( $fh, $export );
			//echo ( con::$relativeFlexPath."/control/"
						."AppController_include.as<br />" );
			fclose( $fh );
		}
		else if ( $assoc['constraint_type'] == 'FOREIGN KEY' ) {
		}
		*/
	}
}

foreach( con::$tables as $tablename=>$columns ) {
	// find columns that are referenced by other tables
	foreach( $columns as $k=>$column ) {
		con::$tables[$tablename][$k][3] =
			findReferencesToColumn( $tablename, $column[0] );
	}
}




// create array of tables for only mapping
con::$manyToMany= array();
foreach( con::$tables as $tableName=>$tableElement ) {

	$allfkeys = sizeof($tableElement)>0;
	foreach( $tableElement as $colIndex=>$column ) {
		if( ! array_key_exists(2, $column )
				|| ($column[2]['constraint_type'] != 'FOREIGN KEY') ) {
			$allfkeys = false;
		}
	}

	con::$tables[$tableName]['isManyToMany'] =
		$allfkeys && sizeof( $tableElement ) == 2;

	if( con::$tables[$tableName]['isManyToMany'] ) {
		//echo "<font color=\"#aa8833\">";
		//echo "$tableName appears to be a Mapping table skipping ... \n";
		//echo "</font>";
		array_push( con::$manyToMany, $tableElement );
		//continue;
	}
}

foreach( con::$tables as $tableName=>$tableElement ) {

	// create VO's
	//list( $export, $exportAS ) = generateVOs( $tableName, $columns,
	//		$package );
	list( $export, $exportAS ) = generateVOs( $tableElement );


	//echo $export;
	//echo $exportAS;

	// write VO's
	if( ! file_exists( con::$relativeVoPath ) ) {
		mkdir( con::$relativeVoPath );
	}
	//echo "writing to ".con::$relativeVoPath."/$tableName.php\n" ;
	$fh = fopen( con::$relativeVoPath."/".toCamelCase($tableName).".php", "w" );
	fwrite( $fh, $export );
	fclose( $fh );
	$zip->addFile(con::$relativeVoPath."/".toCamelCase($tableName).".php",
		con::$absoluteVoPath."/".toCamelCase($tableName).".php");
	//echo con::$relativeVoPath."/".toCamelCase($tableName).".php<br />";
	$fh = fopen( con::$relativeFlexVoPath."/".toCamelCase($tableName).".as",
			"w" );
	fwrite( $fh, $exportAS );
	fclose( $fh );
	$zip->addFile(con::$relativeFlexVoPath."/".toCamelCase($tableName).".as",
		con::$absoluteFlexVoPath."/".toCamelCase($tableName).".as");
	//echo con::$relativeFlexVoPath."/".toCamelCase($tableName).".as<br />";

	$assoc = $tableElement[0][2];
	// write Dao
	$exportDao = generateDaoForTable( $tableElement, con::$relativePath );
	$fh = fopen( con::$relativePath."/".toCamelCase(
				$assoc['table_name'])."Dao.php", "w" );
	fwrite( $fh, $exportDao );
	//echo con::$relativePath."/".toCamelCase($assoc['table_name'])."Dao.php <br />" ;
	fclose( $fh );
	$zip->addFile(  con::$relativePath."/".toCamelCase($assoc['table_name'])."Dao.php",
			con::$absolutePath."/".toCamelCase($assoc['table_name'])."Dao.php");

	// write Dao includes
	/*$tmppath = con::$relativePath."/".toCamelCase(
				   $assoc['table_name']	).".include" ;
	if( ! file_exists( $tmppath ) ) {
		$fh = fopen( $tmppath, "w" );
		fwrite( $fh, "//custom code goes here" );
		fclose( $fh);
	}
	*/

	// write Command
	$exportCommand = generateCommandForTable( $tableElement);
	if( ! file_exists( con::$relativeFlexPath."/command/" ) ) {
		mkdir (con::$relativeFlexPath."/command/" ) ;
	}
	$fh = fopen( con::$relativeFlexPath."/command/".toCamelCase($assoc['table_name'])."Command.as", "w" );
	fwrite( $fh, $exportCommand );
	//echo ( con::$relativeFlexPath."/command/".toCamelCase($assoc['table_name'])."Command.as<br />" );
	fclose( $fh );
	$zip->addFile(  con::$relativeFlexPath."/command/".toCamelCase($assoc['table_name'])."Command.as",
			con::$absoluteFlexPath."/command/".toCamelCase($assoc['table_name'])."Command.as");

	// write Command includes
	/*$tmppath = con::$relativeFlexPath."/command/".toCamelCase(
				   $assoc['table_name']	)."_execinclude.as" ;
	if( ! file_exists( $tmppath ) ) {
		$fh = fopen( $tmppath, "w" );
		fwrite( $fh, "//custom code goes here" );
		fclose( $fh);
	}
	$tmppath = con::$relativeFlexPath."/command/".toCamelCase(
				   $assoc['table_name']	)."_resultinclude.as" ;
	if( ! file_exists( $tmppath ) ) {
		$fh = fopen( $tmppath, "w" );
		fwrite( $fh, "//custom code goes here" );
		fclose( $fh);
	}
	$tmppath = con::$relativeFlexPath."/command/".toCamelCase(
				   $assoc['table_name']	)."_include.as" ;
	if( ! file_exists( $tmppath ) ) {
		$fh = fopen( $tmppath, "w" );
		fwrite( $fh, "//custom code goes here" );
		fclose( $fh);
	}
	*/

	// write Event
	$exportEvent = generateEventForTable( $tableElement );
	if( ! file_exists( con::$relativeFlexPath."/event/" ) ) {
		mkdir (con::$relativeFlexPath."/event/" ) ;
	}
	$fh = fopen( con::$relativeFlexPath."/event/".toCamelCase($assoc['table_name'])."Event.as", "w" );
	fwrite( $fh, $exportEvent );
	//echo ( con::$relativeFlexPath."/event/".toCamelCase($assoc['table_name'])."Event.as<br />" );
	fclose( $fh );
	$zip->addFile(  con::$relativeFlexPath."/event/".toCamelCase($assoc['table_name'])."Event.as",
			con::$absoluteFlexPath."/event/".toCamelCase($assoc['table_name'])."Event.as");

	// write Event includes
	/*$tmppath = con::$relativeFlexPath."/event/".toCamelCase(
				   $assoc['table_name']	)."_include.as" ;
	if( ! file_exists( $tmppath ) ) {
		$fh = fopen( $tmppath, "w" );
		fwrite( $fh, "//custom code goes here" );
		fclose( $fh);
	}
	*/
	// don't write flex for mapping tables
	if( ! array_key_exists('isManyToMany', $tableElement)
			|| $tableElement['isManyToMany'] ) {
		continue;
	}
	// write Model
	/*
	$exportModel = generateModelForTable( $assoc );
	if( ! file_exists( con::$relativeFlexPath."/model/" ) ) {
		mkdir (con::$relativeFlexPath."/model/" ) ;
	}
	$fh = fopen( con::$relativeFlexPath."/model/".toCamelCase($assoc['table_name'])."Model.as", "w" );
	fwrite( $fh, $exportModel );
	//echo ( con::$relativeFlexPath."/model/".toCamelCase($assoc['table_name'])."Model.as<br />" );
	fclose( $fh );
	$zip->addFile(  con::$relativeFlexPath."/model/".toCamelCase($assoc['table_name'])."Model.as",
			con::$absoluteFlexPath."/model/".toCamelCase($assoc['table_name'])."Model.as");

	*/
	// write Test
	$export = generateTestForTable( $tableElement );
	if( ! file_exists( con::$relativeFlexPath."/view/" ) ) {
		mkdir (con::$relativeFlexPath."/view/" ) ;
	}
	$fh = fopen( con::$relativeFlexPath."/view/".toCamelCase($assoc['table_name'])."View.mxml", "w" );
	fwrite( $fh, $export );
	//echo ( con::$relativeFlexPath."/model/".toCamelCase($assoc['table_name'])."Test.mxml<br />" );
	fclose( $fh );
	$zip->addFile(  con::$relativeFlexPath."/view/".toCamelCase($assoc['table_name'])."View.mxml",
			con::$absoluteFlexPath."/view/".toCamelCase($assoc['table_name'])."View.mxml");

}
// write AppController
$export = generateAppController( con::$tables );
if( ! file_exists( con::$relativeFlexPath."/control/" ) ) {
	mkdir (con::$relativeFlexPath."/control/" ) ;
}
$fh = fopen( con::$relativeFlexPath."/control/"."AppController.as", "w" );
		// we append here since we deleted the file at the
		// beginning
fwrite( $fh, $export );
//echo ( con::$relativeFlexPath."/control/"."AppController.as<br />" );
fclose( $fh );
$zip->addFile(  con::$relativeFlexPath."/control/"."AppController.as",
		con::$absoluteFlexPath."/control/"."AppController.as");

// write AppModel
$export = generateAppModel( con::$tables );
if( ! file_exists( con::$relativeFlexPath."/model/" ) ) {
	mkdir (con::$relativeFlexPath."/model/" ) ;
}
$fh = fopen( con::$relativeFlexPath."/model/"."AppModel.as", "w" );
		// we append here since we deleted the file at the
		// beginning
fwrite( $fh, $export );
//echo ( con::$relativeFlexPath."/Model/"."AppModel.as<br />" );
fclose( $fh );
$zip->addFile(  con::$relativeFlexPath."/model/"."AppModel.as",
		con::$absoluteFlexPath."/model/"."AppModel.as");

// write Command includes
/*$tmppath = con::$relativeFlexPath."/control/AppController_include.as" ;
if( ! file_exists( $tmppath ) ) {
	$fh = fopen( $tmppath, "w" );
	fwrite( $fh, "//custom code goes here" );
	fclose( $fh);
}
*/
//echo ( "\con::$tables dump" );
//var_dump( con::$tables );

// find all tables with only 2 foreign keys, and no other columns
// and run appropriate functions on them
foreach( con::$tables as $tablename=>$columns ) {
	$fkeyscount = 0;
	if( sizeof( $columns ) < 3 ) {
		for( $i = 0; $i < sizeof( $columns ); $i++ ) {
			if( array_key_exists( 2, $columns[$i] ) &&
					$columns[$i][2]['constraint_type'] == 'FOREIGN KEY' ) {
				$fkeyscount++;
			}
		}
	}
	if( $fkeyscount == 2 ) {	# columns is no more than 3 because of earlier
								# if, and columns is no less than $fkeyscount

		addMappingTable( con::$tables, $tablename );
	}
}

// find all tables with a primary key
// add them to services.mxml and others a necessary
#var_dump( con::$tables );
#echo  "<br />";
$primaryTables = array();
foreach( con::$tables as $tablename=>$columns ) {
	foreach( $columns as $i=>$value ) {
		if( ! is_int( $i ) ) {
			continue;
		}
		if( array_key_exists( 2, $columns[$i] ) &&
				$columns[$i][2]['constraint_type'] == 'PRIMARY KEY' ) {
			$primaryTables[$tablename] = con::$tables[$tablename] ;
			break;
		}
	}
}
#var_dump( $primaryTables );
#echo "<br />";

$export = generateServicesMxml( $primaryTables );
if( !file_exists( con::$relativeFlexPath."/business/" )) {
	mkdir( con::$relativeFlexPath."/business/" );
}
$fh = fopen( con::$relativeFlexPath."/business/Services.mxml", "w" );
//echo( con::$relativeFlexPath."/business/Services.mxml<br />" );
fwrite( $fh, $export );
fclose( $fh );
$zip->addFile( con::$relativeFlexPath."/business/Services.mxml",
		con::$absoluteFlexPath."/business/Services.mxml");

// write remoting-config.xml
$export = generateRemotingConfig( $primaryTables );
if( !file_exists( con::$relativeFlexSrcPath."/" )) {
	mkdir( con::$relativeFlexSrcPath."/" );
}
$fh = fopen( con::$relativeFlexSrcPath."/remoting-config.xml", "w" );
//echo( con::$relativeFlexSrcPath."/remoting-config.xml<br />" );
fwrite( $fh, $export );
fclose( $fh );
$zip->addFile(con::$relativeFlexSrcPath."/remoting-config.xml",
		con::$absoluteFlexSrcPath."/remoting-config.xml");


// generate eclipse project files required for a flex project
$export = generateEclipseFiles();
if( !file_exists( con::$relativeFlexRootPath."/" )) {
	mkdir( con::$relativeFlexRootPath."/" );
}
//if( ! is_file( con::$relativeFlexRootPath.'.project' ) ) {
	$fh = fopen( con::$relativeFlexRootPath.".project", "w" );
	//echo( con::$relativeFlexRootPath.".project <br />" );
	fwrite( $fh, $export );
	fclose( $fh );
//}
$zip->addFile(con::$relativeFlexRootPath.".project",
		con::$absoluteFlexRootPath.".project");

// generate eclipse actionscriptproperties file required for flex project
$export = generateActionScriptPropertiesFile();
if( !file_exists( con::$relativeFlexRootPath."/" )) {
	mkdir( con::$relativeFlexRootPath."/" );
}
//if( ! is_file( con::$relativeFlexRootPath.'.actionScriptProperties' ) ) {
	$fh = fopen( con::$relativeFlexRootPath.".actionScriptProperties", "w" );
	//echo( con::$relativeFlexRootPath.".actionScriptProperties <br />" );
	fwrite( $fh, $export );
	fclose( $fh );
//}
$zip->addFile(con::$relativeFlexRootPath.".actionScriptProperties",
			con::$absoluteFlexRootPath.".actionScriptProperties");

// generate mxml containing all the test mxmls
$export = generateTestMxml();
if( !file_exists( con::$relativeFlexSrcPath."/" )) {
	mkdir( con::$relativeFlexSrcPath."/" );
}
$fh = fopen( con::$relativeFlexSrcPath."/test.mxml", "w" );
//echo( con::$relativeFlexSrcPath."/test.mxml <br />" );
fwrite( $fh, $export );
fclose( $fh );
$zip->addFile(con::$relativeFlexSrcPath."/test.mxml",
		con::$absoluteFlexSrcPath."/test.mxml");

#add stdFunc
	$zip->addFile(con::$relativePath."/StdFunc.php",
		con::$absolutePath."/StdFunc.php");
#clean up zip stuff
$zip->close();

# log hits
$fp = fopen("../log.html", "a");
fputs($fp,date("m.d,  h:i:s").', '.GetHostByName($_SERVER['REMOTE_ADDR']).', Generated, Server: '.con::$dbhost.', '.$zipName.'<br/>');
fclose( $fp);

# tell that we are finished
echo "<h1>Code Generation Completed Successfully!</h1>";


echo "</pre></code>\n";

echo "<h1>Instructions:</h1>
<ol>
";
echo "
<li>Download the generated files <a href=\"/php/generated/$zipName\">here</a>.</li>\n";

echo "
<li>Open the Zip File.  Copy the folders (com, vo) in the amfphp/services folder to your own amfphp services folder.  Take
care to keep all the php files in their existing package structure, otherwise RemoteClassing might fail.</li>\n";

echo "
<li>Edit the StdFunc.php file (".con::$absolutePath."/StdFunc.php) to point to the
correct database with the proper login credentials.  We do update StdFunc.php however for security
reasons, you'll probably be wanting to change these parameters.</li>\n";

echo "
<li>Import the autogenerated Flex project into Eclipse.  The project has already been configured
to use the latest Cairngorm library and the default amfphp remoting gateway
(http://{server.name}:{server.port}/flashservices/gateway.php).  The only error that you should
see upon import is that the html-template folder doesn't exist, and right clicking
on that error will restore it.</li>\n";

echo "
<li>Compile and run the flex application.  Make sure that your amfphp server is up and running.  we
have generated a default testing UI that should give you immediate results.</li>\n";


echo "</ol>\n";

echo "<p><strong>DISCLAIMER:  Use at your own risk!<strong></p>";
echo "</body>\n</html>";

?>
